package com.qiong.mvnbook.account.captcha;

import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.imageio.ImageIO;
import javax.security.auth.login.AccountException;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

public class AccountCaptchaServiceImpl implements AccountCaptchaService, InitializingBean {

    private DefaultKaptcha producer;

    private Map<String, String> captchaMap = new HashMap<>();

    private List<String> preDefinedTexts;

    private int textCount = 0;

    @Override
    public void afterPropertiesSet() throws Exception {
        producer = new DefaultKaptcha();
        producer.setConfig(new Config(new Properties()));
    }

    @Override
    public String generateCaptchaKey() {
        String key = RandomGenerator.getRandomString();
        String value = getCaptchaText();
        captchaMap.put(key, value);
        return key;
    }

    private String getCaptchaText() {
        if (!CollectionUtils.isEmpty(preDefinedTexts)) {
            String text = preDefinedTexts.get(textCount);
            textCount = (textCount + 1) % preDefinedTexts.size();
            return text;
        } else
            return producer.createText();
    }

    @Override
    public byte[] generateCaptchaImage(String captchaKey) throws AccountException {
        String text = captchaMap.get(captchaKey);
        if (text == null) {
            throw new AccountException("Captcha key '" + captchaKey + "' not found!");
        }
        BufferedImage image = producer.createImage(text);
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        try {
            ImageIO.write(image, "jpg", out);
        } catch (IOException e) {
            e.printStackTrace();
            throw new AccountException("Failed to write captcha stream!");
        }
        return out.toByteArray();
    }

    @Override
    public boolean validateCaptcha(String captchaKey, String captchaValue) throws AccountException {
        String text = captchaMap.get(captchaKey);
        if (text == null) {
            throw new AccountException("Captcha key '" + captchaKey + "' not found!");
        }
        if (text.equals(captchaValue)) {
            captchaMap.remove(captchaKey);
            return true;
        } else
            return false;
    }

    @Override
    public List<String> getPreDefinedTexts() {
        return preDefinedTexts;
    }

    @Override
    public void setPreDefinedTexts(List<String> preDefinedTexts) {
        this.preDefinedTexts = preDefinedTexts;
    }
}
